An object-oriented computer program contains interacting objects that carry out specific program logic. Single process programming techniques assume that all objects reside within the same process hosted on a single computer system. Distributed programming systems, on the other hand, are designed to support objects across multiple processes, usually hosted on separate computers. For distributed systems, typically only certain objects explicitly—declared and programmed as “remote” objects by the programmer—can be remotely accessed by other objects. From the perspective of any given object, only remote objects can be invoked remotely, and only local objects can be invoked locally, with the distinction between local and remote objects being fixed by the application code. Thus, changing a local object to a remote object requires reprogramming.
One problem with legacy applications not written for a distributed computing environment is that the applications must be modified to execute across multiple processes. Similarly, current object-oriented distributed computing infrastructures require programmatic specification of which objects can be remotely accessed by classifying the objects into remote objects and local objects. Such classification requires expertise in distributed programming techniques as well as a priori knowledge of the program flow. Legacy applications that were built to run in a single process on a single host often require extensive reprogramming to execute in a distributed environment. Such modifications can be costly, and also require extensive knowledge of program flow and distributed programming expertise, for example, to avoid errors arising from the differing semantics used for remote and local object invocations. Such errors can be extremely time-consuming and difficult to identify and debug.
Another problem with previously-known distributed systems is that invocation of a remote object often uses different semantics than are used to invoke a local object. Specifically, when an object invokes a local object, all parameters are passed according to the semantics defined by the programming language. In Java, for example, all parameter objects and return values are effectively passed by reference, i.e., by passing an object reference in the parameter list. When an object invokes a remote object, the local objects in the parameter list are passed by copy, while the remote objects in the parameter list are passed by reference. Duplication of the local objects requires that those objects be specially tagged and special code is sometimes required to ensure correct copies are made. In Common Object Request Broker Architecture (“CORBA”) applications, all of the passed object types must be properly defined in the interface definition language for any object types that are in the method signature of a remote object. Web services, including .NET, require the definition using the web service description language. All of this special coding presents an additional error-prone burden for the programmer. The different invocation semantics also are complicated because, depending on what kind of object is invoked, local or remote, either a reference to a parameter object is passed or a reference to a copy of the object is passed—often leading to numerous programming errors that are difficult to solve.
The ability to migrate objects between processes is useful when executing a program whose objects are spread across multiple hosts. This capability supports dynamic processor and network load balancing. In addition, it facilitates system maintenance because objects can be migrated off of a host requiring upgrades or repair. In many distributed systems, the mapping of objects to processes and hosts must remain fixed throughout a given execution of the program. Even for those programs that support migration, only the remote objects can be migrated. This can be limiting, however, as the number of remote objects is usually much smaller than the number of local objects, and thus constrains the degree of load balancing that can be achieved.
Another short-coming of many previously-known distributed systems is that the mapping of objects to a process is static, i.e., the mapping cannot be reconfigured while the application is running to optimize processor or network load. Even those systems that support migration of objects between processes are limited in their potential mappings because only remote objects can be migrated. In addition, there are typically many more local objects than remote objects, thus adversely impacting the ability of a system administrator to balance network loads.
Yet another problem with static mapping is the inability to perform system maintenance during runtime. When all objects cannot be migrated, then it is not possible to shutdown a host involved in executing a distributed application, e.g., for system upgrade or routine maintenance, without terminating the execution of the application. This planned downtime and resulting service disruption is undesirable for systems requiring high availability.
While most systems do not use dynamic code modification, some techniques are known for supporting the distributed execution of applications. One such system developed by Michiaki Tatsubori of the University of Tsukuba, Japan, and called Addistant, uses code modification to support automatic distributed execution of legacy Java software. At class definition load time, that is, class file loading in Java terms, the system modifies the bytecode of the Java class, so that objects based on the modified classes can execute within a process distinct from the main process of the application. A number of modification techniques are used to achieve this effect. However, Addistant does not support dynamic migration of objects, and the mapping of objects to processes and hosts is explicit and static. Thus, the administrator must define a runtime policy file that indicates which objects, which may be grouped by class, run on which processes. Consequently, the static mapping precludes dynamic processor and network load balancing, as there is no way to move all objects off of a host for system maintenance purposes without halting and restarting the application.
It would therefore be desirable to provide a system and methods that overcome these and other disadvantages of previously-known systems.